1 module modular_db.database; 2 3 public import d2sqlite3; 4 5 @system: 6 7 struct Transaction { 8 private { 9 d2sqlite3.Database _db; 10 bool _nested; 11 } 12 13 package this(d2sqlite3.Database db, bool nested) { 14 db.execute(nested ? "SAVEPOINT _modular_db_save" : "BEGIN"); 15 _db = db; 16 _nested = nested; 17 } 18 19 @disable this(this); 20 21 ~this() { 22 if (_db !is d2sqlite3.Database.init) 23 _db.execute(_nested ? "ROLLBACK TO _modular_db_save" : "ROLLBACK"); 24 } 25 26 @property bool nested() const nothrow pure @safe @nogc { 27 return _nested; 28 } 29 30 void commit() 31 in { 32 assert(_db !is d2sqlite3.Database.init, "Attempting to commit a closed transaction"); 33 } 34 do { 35 _db.execute(_nested ? "RELEASE _modular_db_save" : "COMMIT"); 36 _db = d2sqlite3.Database.init; 37 } 38 } 39 40 // N.B.: Make it ref-counted if adding extra fields. 41 struct Database { 42 d2sqlite3.Database raw; 43 44 alias raw this; 45 46 @property bool inTransaction() nothrow 47 in { 48 assert(raw.handle !is null, "Attempting to query transaction status in a closed database"); 49 } 50 do { 51 import d2sqlite3.sqlite3; 52 53 return !sqlite3_get_autocommit(raw.handle); 54 } 55 56 Transaction startTransaction() 57 in { 58 assert(raw.handle !is null, "Attempting to start a transaction in a closed database"); 59 } 60 do { 61 return Transaction(raw, inTransaction); 62 } 63 }